package me.zhengjie.modules.system.service.impl;

import cn.hutool.core.util.IdUtil;
import me.zhengjie.modules.system.domain.Department;
import me.zhengjie.modules.system.repository.DepartmentRepository;
import me.zhengjie.modules.system.service.DepartmentService;
import me.zhengjie.modules.system.service.dto.DepartmentDTO;
import me.zhengjie.modules.system.service.dto.DepartmentQueryCriteria;
import me.zhengjie.modules.system.service.mapper.DepartmentMapper;
import me.zhengjie.utils.*;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author Zhang xing wang
* @date 2020-03-26
*/
@Service
@CacheConfig(cacheNames = "department")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DepartmentServiceImpl implements DepartmentService {

    private final DepartmentRepository departmentRepository;

    private final DepartmentMapper departmentMapper;

    public DepartmentServiceImpl(DepartmentRepository departmentRepository, DepartmentMapper departmentMapper) {
        this.departmentRepository = departmentRepository;
        this.departmentMapper = departmentMapper;
    }

    @Override
    @Cacheable
    public Map<String,Object> queryAll(DepartmentQueryCriteria criteria, Pageable pageable){
        Page<Department> page = departmentRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(departmentMapper::toDto));
    }

    @Override
    @Cacheable
    public List<DepartmentDTO> queryAll(DepartmentQueryCriteria criteria){
        return departmentMapper.toDto(departmentRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Cacheable(key = "#p0")
    public DepartmentDTO findById(String id) {
        Department department = departmentRepository.findById(id).orElseGet(Department::new);
        ValidationUtil.isNull(department.getId(),"Department","id",id);
        return departmentMapper.toDto(department);
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public DepartmentDTO create(Department resources) {
        resources.setId(IdUtil.simpleUUID()); 
        return departmentMapper.toDto(departmentRepository.save(resources));
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void update(Department resources) {
        Department department = departmentRepository.findById(resources.getId()).orElseGet(Department::new);
        ValidationUtil.isNull( department.getId(),"Department","id",resources.getId());
        department.copy(resources);
        departmentRepository.save(department);
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void delete(String id) {
        departmentRepository.deleteById(id);
    }


    @Override
    public void download(List<DepartmentDTO> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (DepartmentDTO department : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("父类id", department.getParentId());
            map.put("名称", department.getName());
            map.put("医院ID", department.getHospitalId());
            map.put("编码", department.getCode());
            map.put("创建者", department.getCreateBy());
            map.put("更新者", department.getUpdateBy());
            map.put("备注信息", department.getRemarks());
            map.put("删除标记", department.getDelFlag());
            map.put(" ksImage",  department.getKsImage());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Map<String, Object> terrDepartment(List<DepartmentDTO> list) {
        Set<DepartmentDTO> trees = new LinkedHashSet<>();
        Set<DepartmentDTO> departmentTrees = new LinkedHashSet<>();
        List<String> getNames = list.stream().map(DepartmentDTO::getName).collect(Collectors.toList());
        boolean isChild;
        for (DepartmentDTO departmentDTO: list) {
            isChild = false;
            if(StringUtils.equals(departmentDTO.getParentId(), "0")){
                trees.add(departmentDTO);//科室
            }
            for (DepartmentDTO it : list) {
                if (it.getParentId().equals(departmentDTO.getId())) {
                    isChild = true;
                    if (departmentDTO.getChildren() == null) {
                        departmentDTO.setChildren(new ArrayList<>());
                    }
                    departmentDTO.getChildren().add(it);
                }
            }
            if(isChild){
                departmentTrees.add(departmentDTO);
            }else if(!getNames.contains(departmentRepository.findNameById(departmentDTO.getParentId()))){
                departmentTrees.add(departmentDTO);
            }
        }
        if (CollectionUtils.isEmpty(trees)) {
            trees = departmentTrees;
        }
        Map<String,Object> map = new HashMap<>();
       // map.put("totalElements",totalElements);
        map.put("content",CollectionUtils.isEmpty(trees)?departmentTrees:trees);
        return map;
    }

    private DepartmentDTO trees(List<DepartmentDTO> list, DepartmentDTO departmentDTO) {
        boolean falg;
        for (DepartmentDTO dto : list) {
            if(StringUtils.equals(dto.getParentId(), departmentDTO.getId())){
                falg = true;
                if(departmentDTO.getChildren() == null){
                    departmentDTO.setChildren(new ArrayList<>());
                }
                departmentDTO.getChildren().add(dto);
            }

        }
        return departmentDTO;
    }
}